home *** CD-ROM | disk | FTP | other *** search
- /* bmutil.c */
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <time.h>
- #include <stdlib.h>
- #include <errno.h>
- #include "bm.h"
- #include "header.h"
-
- static unsigned long mboxsize;
- static int anyread;
-
- int initnotes(void)
- {
- FILE *ifile;
- register struct let *cmsg;
- int i, ret;
- struct stat mstat;
-
- if (!stat(mfilename,&mstat))
- mboxsize = mstat.st_size;
- if ((ifile = fopen(mfilename,"rt")) == NULLFILE) {
- panic(nomail);
- mfile = NULLFILE;
- return 0;
- }
- if ((mfile = tmpfile()) == NULLFILE) {
- panic("Unable to create tmp file");
- fclose(ifile);
- return -1;
- }
- nmsgs = 0;
- current = 0;
- change = 0;
- newmsgs = 0;
- anyread = 0;
- ret = readnotes(ifile);
- fclose(ifile);
- if (ret != 0)
- return -1;
- for (cmsg = &mbox[1],i = 1; i <= nmsgs; i++, cmsg++)
- if ((cmsg->status & READ) == 0) {
- newmsgs++;
- if (current == 0)
- current = i;
- }
- /* start at one if no new messages */
- if (current == 0)
- current++;
-
- return 0;
-
- }
-
- /* readnotes assumes that ifile is pointing to the first
- * message that needs to be read. For initial reads of a
- * notesfile, this will be the beginning of the file. For
- * rereads when new mail arrives, it will be the first new
- * message.
- */
- int readnotes(FILE *ifile)
- {
- char tstring[LINELEN];
- long cpos;
- register struct let *cmsg;
- register char *line;
-
- cmsg = (struct let *)NULL;
- line = tstring;
- while(!feof(ifile)) {
- fgets(line,LINELEN,ifile);
- /* scan for begining of a message */
- if(strncmp(line,"From ",5) == 0) {
- cpos = ftell(mfile);
- fputs(line,mfile);
- if (nmsgs == maxlet) {
- panic("Mail box full: > %d messages\n",maxlet);
- fclose(mfile);
- return -1;
- }
- nmsgs++;
- cmsg = &mbox[nmsgs];
- cmsg->start = cpos;
- cmsg->status = 0;
- cmsg->size = strlen(line);
- while (!feof(ifile)) {
- if (fgets(line,LINELEN,ifile) == NULLCHAR)
- break;
- if (*line == '\n') { /* done header part */
- cmsg->size++;
- putc(*line, mfile);
- break;
- }
- if (htype(line) == STATUS) {
- if (line[8] == 'R')
- cmsg->status |= READ;
- continue;
- }
- cmsg->size += strlen(line);
- if (fputs(line,mfile) == EOF) {
- panic("%s: %s", "tmp file", strerror(errno));
- fclose(mfile);
- return -1;
- }
-
- }
- } else if (cmsg) {
- cmsg->size += strlen(line);
- fputs(line,mfile);
- }
- }
- return 0;
- }
-
- /* list headers of a notesfile a message */
- void listnotes(void)
- {
- register struct let *cmsg;
- register char *p, *s;
- char smtp_date[SLINELEN];
- char smtp_from[SLINELEN];
- char smtp_subject[SLINELEN];
- char tstring[LINELEN];
- int i;
- long size;
-
- /*
- if (mfile == NULLFILE)
- return;
- */
-
- if (!wopen(LISTNOTES)) {
- panic("Cannot open List Notes window.");
- return;
- }
-
- wclear(LISTNOTES);
-
- wprintf(LISTNOTES, "Mailbox %s - %d messages %d new\n\n",mfilename,nmsgs,newmsgs);
-
- for (cmsg = &mbox[1],i = 1; i <= nmsgs; i++, cmsg++) {
- *smtp_date = '\0';
- *smtp_from = '\0';
- *smtp_subject = '\0';
- fseek(mfile,cmsg->start,0);
- size = cmsg->size;
- while (!feof(mfile) && size > 0) {
- fgets(tstring,sizeof(tstring),mfile);
- if (*tstring == '\n') /* end of header */
- break;
- size -= strlen(tstring);
- rip(tstring);
- /* handle continuation later */
- if (*tstring == ' '|| *tstring == '\t')
- continue;
- switch(htype(tstring)) {
- case FROM:
- if((p = getname(tstring)) == NULLCHAR) {
- p = &tstring[6];
- while(*p && *p != ' ' && *p != '(')
- p++;
- *p = '\0';
- p = &tstring[6];
- }
- sprintf(smtp_from,"%.30s",p);
- break;
- case SUBJECT:
- sprintf(smtp_subject,"%.34s",&tstring[9]);
- break;
- case DATE:
- if ((p = strchr(tstring,',')) == NULLCHAR)
- p = &tstring[6];
- else
- p++;
- /* skip spaces */
- while (*p == ' ') p++;
- if(strlen(p) < 17)
- break; /* not a valid length */
- s = smtp_date;
- /* copy day */
- if (atoi(p) < 10 && *p != '0') {
- *s++ = ' ';
- } else
- *s++ = *p++;
- *s++ = *p++;
-
- *s++ = ' ';
- while (*p == ' ')
- p++;
- /* copy month */
- *s++ = *p++;
- *s++ = *p++;
- *s++ = *p++;
- while (*p == ' ')
- p++;
- /* skip year */
- while (isdigit(*p))
- p++;
- /* copy time */
- *s++ = *p++; /* space */
- *s++ = *p++; /* hour */
- *s++ = *p++;
- *s++ = *p++; /* : */
- *s++ = *p++; /* min */
- *s++ = *p++;
- *s = '\0';
- break;
- case NOHEADER:
- break;
- }
- }
- wprintf(LISTNOTES, "%c%c%c%3d %-27.27s %-12.12s %5ld %.25s\n",
- (i == current ? '>' : ' '),
- (cmsg->status & DELETE ? 'D' : ' '),
- (cmsg->status & READ ? 'Y' : 'N'),
- i, smtp_from, smtp_date,
- cmsg->size, smtp_subject);
- }
-
- whome(LISTNOTES);
- }
-
- /* save msg on stream - if noheader set don't output the header */
- int msgtofile(int msg, FILE *tfile, int noheader)
- {
- char tstring[LINELEN];
- long size;
-
- if (mfile == NULLFILE) {
- panic(nomail);
- return -1;
- }
- fseek(mfile,mbox[msg].start,0);
- size = mbox[msg].size;
- if ((mbox[msg].status & READ) == 0) {
- mbox[msg].status |= READ;
- change = 1;
- }
-
- if (noheader) {
- /* skip header */
- while (!feof(mfile) && size > 0) {
- fgets(tstring,sizeof(tstring),mfile);
- size -= strlen(tstring);
- if (*tstring == '\n')
- break;
- }
- }
- while (!feof(mfile) && size > 0) {
- fgets(tstring,sizeof(tstring),mfile);
- size -= strlen(tstring);
- fputs(tstring,tfile);
- if (ferror(tfile)) {
- panic("Error writing mail file");
- fclose(tfile);
- return -1;
- }
- }
- return 0;
- }
-
- /* delmsg - delete message in current notesfile */
- void delmsg(int msg)
- {
- if (mfile == NULLFILE) {
- panic(nomail);
- return;
- }
- mbox[msg].status |= DELETE;
- change = 1;
- }
-
- /* reply - to a message */
- void reply(int msg)
- {
- char to[SLINELEN];
- char subject[LINELEN];
- char tstring[LINELEN];
- char *p,*s;
- long size;
-
- if (mfile == NULLFILE) {
- panic(nomail);
- return;
- }
- *to = '\0';
- *subject = '\0';
- fseek(mfile,mbox[msg].start,0);
- size = mbox[msg].size;
- while (!feof(mfile) && size > 0) {
- fgets(tstring,sizeof(tstring),mfile);
- size -= strlen(tstring);
- if (*tstring == '\n') /* end of header */
- break;
- rip(tstring);
- if ((*to == '\0' && htype(tstring) == FROM)
- || htype(tstring) == REPLYTO) {
- s = getname(tstring);
- if (s == NULLCHAR) {
- p = strchr(tstring,':');
- p += 2;
- s = p;
- while(*p && *p != ' ' && *p != '(')
- p++;
- *p = '\0';
- }
- *to = '\0';
- strncat(to,s,sizeof(to));
- } else if (htype(tstring) == SUBJECT) {
- if (strncmp(&tstring[9], "Re:", 3)) /* No Re: yet? */
- sprintf(subject,"Re: %s\n",&tstring[9]);
- else /* there's an Re:, let's not add another */
- sprintf(subject,"%s\n",&tstring[9]) ;
- }
- }
- if (*to == '\0')
- panic("No reply address in message\n");
- else
- dosmtpsend(NULLFILE,to,subject);
- }
-
-
- /* close the temp file while coping mail back to the mailbox */
- int closenotes(void)
- {
- register struct let *cmsg;
- register char *line;
- char tstring[LINELEN];
- long size;
- int i;
- int ret;
- int written = 0;
- FILE *nfile;
-
- if (mfile == NULLFILE)
- return 0;
- if (!change) {
- fclose(mfile);
- return 0;
- }
- line = tstring;
- fseek(mfile,0L,2);
- if (isnewmail()) {
-
- panic("isnewmail = TRUE\n");
-
- if ((nfile = fopen(mfilename,"rt")) == NULLFILE)
- panic("%s: %s", mfilename, strerror(errno));
- else {
- /* seek to end of old msgs */
- fseek(nfile,mboxsize,0);
- /* seek to end of tempfile */
- fseek(mfile,0L,2);
- ret = readnotes(nfile); /* get the new mail */
- fclose(nfile);
- if (ret != 0) {
- panic("Error updating mail file\n");
- return -1;
- }
- }
- }
-
- if ((nfile = fopen(mfilename,"wt")) == NULLFILE) {
- panic("Unable to open %s\n",mfilename);
- return -1;
- }
- /* copy tmp file back to notes file */
- for (cmsg = &mbox[1],i = 1; i <= nmsgs; i++, cmsg++) {
- fseek(mfile,cmsg->start,0);
- size = cmsg->size;
- if ((cmsg->status & DELETE))
- continue;
-
- written++;
- /* copy the header */
- while (!feof(mfile) && size > 0) {
- fgets(line,LINELEN,mfile);
- size -= strlen(line);
- if (*line == '\n') {
- if ((cmsg->status & READ) != 0)
- fprintf(nfile,"Status: R\n");
- fprintf(nfile,"\n");
- break;
- }
- fputs(line,nfile);
- }
- while (!feof(mfile) && size > 0) {
- fgets(line,LINELEN,mfile);
- fputs(line,nfile);
- size -= strlen(line);
- if (ferror(nfile)) {
- panic("Error writing mail file\n");
- fclose(nfile);
- fclose(mfile);
- return -1;
- }
- }
- }
- nmsgs = 0;
- fclose(nfile);
- fclose(mfile);
- mfile = NULLFILE;
-
- if (written == 0)
- remove(mfilename);
-
- return 0;
- }
-
- /* get a message id from the sequence file */
- long get_msgid(void)
- {
- char sfilename[SLINELEN];
- char s[20];
- long sequence = 0L;
- FILE *sfile;
-
- sprintf(sfilename,"%s.sequence", mqueue);
- sfile = fopen(sfilename,"rt");
-
- /* if sequence file exists, get the value, otherwise set it */
- if (sfile != NULLFILE) {
- fgets(s,sizeof(s),sfile);
- sequence = atol(s);
- /* Keep it in range of and 8 digit number to use for dos name prefix. */
- if (sequence < 0L || sequence > 99999999L )
- sequence = 0L;
- fclose(sfile);
- }
-
- /* increment sequence number, and write to sequence file */
- sfile = fopen(sfilename,"wt");
- fprintf(sfile,"%ld",++sequence);
- fclose(sfile);
- return sequence;
- }
-
- /* Given a string of the form <user@host>, extract the part inside the
- * brackets and return a pointer to it.
- */
- char *getname(register char *cp)
- {
- char *cp1;
-
- if((cp = strchr(cp,'<')) == NULLCHAR)
- return NULLCHAR;
- cp++; /* cp -> first char of name */
- if((cp1 = strchr(cp,'>')) == NULLCHAR)
- return NULLCHAR;
- *cp1 = '\0';
- return cp;
- }
-
- /* create mail lockfile */
- int mlock(char *dir, char *id)
- {
- char lockname[SLINELEN];
- FILE *fp;
- /* Try to create the lock file in an atomic operation */
- sprintf(lockname,"%s.lock.%s",dir,id);
- if((fp = fopen(lockname, "wt")) == NULL)
- return -1;
- fclose(fp);
- return 0;
- }
-
- /* remove mail lockfile */
- void rmlock(char *dir, char *id)
- {
- char lockname[SLINELEN];
- sprintf(lockname,"%s.lock.%s",dir,id);
- remove(lockname);
- }
-
- /* parse a line into argv array. Return argc */
- int parse(register char *line, char *argv[], int maxargs)
- {
- int argc;
- int qflag;
- register char *cp;
-
- for(argc = 0; argc < maxargs; argc++)
- argv[argc] = NULLCHAR;
-
- for(argc = 0; argc < maxargs;){
- qflag = 0;
- /* Skip leading white space */
- while(*line == ' ' || *line == '\t')
- line++;
- if(*line == '\0')
- break;
- /* Check for quoted token */
- if(*line == '"'){
- line++; /* Suppress quote */
- qflag = 1;
- }
- argv[argc++] = line; /* Beginning of token */
- /* Find terminating delimiter */
- if(qflag){
- /* Find quote, it must be present */
- if((line = strchr(line,'"')) == NULLCHAR){
- return -1;
- }
- *line++ = '\0';
- } else {
- /* Find space or tab. If not present,
- * then we've already found the last
- * token.
- */
- if((cp = strchr(line,' ')) == NULLCHAR
- && (cp = strchr(line,'\t')) == NULLCHAR){
- break;
- }
- *cp++ = '\0';
- line = cp;
- }
- }
- return argc;
- }
-
- int lockit(void)
- {
- if(mlock(maildir,notename)) {
- panic("Mail file is busy");
- if (mfile != NULLFILE)
- fclose(mfile);
- mfile = NULLFILE;
- return 1;
- }
- return 0;
- }
-
- /* print the next message or the current on of new */
- void printnext(void)
- {
- if (mfile == NULLFILE)
- return;
- if ((mbox[current].status & READ) != 0) {
- if (current == 1 && anyread == 0)
- ;
- else if (current < nmsgs) {
- current++;
- } else {
- panic("Last message");
- return;
- }
- }
- displaymsg(current);
- anyread = 1;
- }
-
- /* display message on the crt given msg number */
- void displaymsg(int msg)
- {
- register int c;
- register int col;
- char buf[200]; /* line buffer */
- int cnt;
- long tsize, size;
-
- if (mfile == NULLFILE) {
- panic(nomail);
- return;
- }
- if( msg < 0 || msg > nmsgs) {
- panic(badmsg,msg);
- return;
- }
-
- if (!wopen(DISPLAYMSG)) {
- panic("Cannot open Message Display window");
- return;
- }
-
- wclear(DISPLAYMSG);
-
- fseek(mfile,mbox[msg].start,0);
- size = mbox[msg].size;
- tsize = size;
-
- wprintf(DISPLAYMSG, "Message #%d %s\n",
- msg, mbox[msg].status & DELETE ? "[Deleted]" : "");
- if ((mbox[msg].status & READ) == 0) {
- mbox[msg].status |= READ;
- change = 1;
- }
- col = 0;
- while (!feof(mfile) && size > 0) {
- for (col = 0; col < 200-1;) {
- c = fgetc(mfile);
- size--;
- if (feof(mfile) || size == 0) /* end this line */
- break;
- if (c == '\t') {
- cnt = col + 8 - (col & 7);
- if (cnt >= 200) /* end this line */
- break;
- while (col < cnt)
- buf[col++] = ' ';
- } else if (c == '\n')
- break;
- else
- buf[col++] = c;
- }
- buf[col] = '\0';
- wprintf(DISPLAYMSG, "%s\n",buf);
- col = 0;
- }
-
- whome(DISPLAYMSG);
- }
-
- /* list jobs wating to be sent in the mqueue */
- void listqueue(void)
- {
- char tstring[80];
- char workfile[80];
- char line[20];
- char host[SLINELEN];
- char to[SLINELEN];
- char from[SLINELEN];
- char status;
- struct stat stbuf;
- FILE *fp;
-
- if (!wopen(LISTQUEUE)) {
- panic("Cannot open List Queue Window");
- return;
- }
-
- wclear(LISTQUEUE);
-
- wprintf(LISTQUEUE, "S Job Size Date Time Host From\n");
-
- sprintf(workfile,"%s.work",mqueue);
- filedir(workfile,0,line);
- while(line[0] != '\0') {
- sprintf(tstring,"%s.work.%s",mqueue,line);
- if ((fp = fopen(tstring,"rt")) == NULLFILE) {
- panic("%s: %s", tstring, strerror(errno));
- continue;
- }
- sprintf(tstring,"%s.lock.%s",mqueue,line);
- if (access(tstring,0))
- status = ' ';
- else
- status = 'L';
- sprintf(tstring,"%s.text.%s",mqueue,line);
- stat(tstring,&stbuf);
- fgets(host,sizeof(host),fp);
- rip(host);
- fgets(from,sizeof(from),fp);
- rip(from);
- wprintf(LISTQUEUE, "%c %7s %7d %s %-20s %s\n ",
- status, line, stbuf.st_size,
- stbuf.st_ctime, host,from);
- while (fgets(to,sizeof(to),fp) != NULLCHAR) {
- rip(to);
- wprintf(LISTQUEUE, "%s ",to);
- }
- wprintf(LISTQUEUE, "\n");
- fclose(fp);
-
- filedir(workfile,1,line);
- }
-
- whome(LISTQUEUE);
- }
-
- /* kill a job in the mqueue */
- void killjob(char *j)
- {
- char s[SLINELEN];
-
- sprintf(s,"%s.lock.%s",mqueue,j);
- remove(s);
- sprintf(s,"%s.work.%s",mqueue,j);
- if (remove(s))
- panic("Job id %s not found\n",j);
- sprintf(s,"%s.text.%s",mqueue,j);
- remove(s);
- }
-
- /* check the current mailbox to see if new mail has arrived.
- * checks to see if the file has increased in size.
- * returns true if new mail has arrived.
- */
- int isnewmail(void)
- {
- struct stat mstat;
- if (mfile == NULLFILE)
- return 0;
- if (stat(mfilename,&mstat))
- panic("unable to stat %s",mfilename);
- else if (mstat.st_size > mboxsize)
- return 1;
- return 0;
- }
-